Sparsetodense ================= 将稀疏张量转换为密集张量。该算子根据稀疏索引和值,将稀疏元素填充到密集张量的对应位置。支持标量值模式(所有位置使用相同的值)和向量值模式(每个索引对应不同的值)。 对于每个稀疏元素,根据其索引计算在密集张量中的线性位置,根据 `is_scalar` 标志,将对应的稀疏值写入密集张量的对应位置 .. math:: \text{output}[\text{index}] = \begin{cases} \text{sparse\_values}[0], & \text{if } \text{is\_scalar} = 1 \\ \text{sparse\_values}[i], & \text{if } \text{is\_scalar} = 0 \end{cases} 输入: - **indices_vec** - 稀疏张量的索引数组,大小为 `sparse_length * 4`,每4个连续的int值表示一个稀疏元素在4维密集张量中的位置坐标 `[dim0, dim1, dim2, dim3]`。 - **sparse_values** - 稀疏张量的值数组。如果 `is_scalar = 1`,只需要 `sparse_values[0]` 有效;如果 `is_scalar = 0`,需要 `sparse_length` 个值。 - **output_strides** - 输出密集张量的步长数组,大小为4,用于将多维索引转换为线性索引。`output_strides[0]`, `output_strides[1]`, `output_strides[2]` 对应前3维的步长,第4维的步长为1。 - **sparse_length** - 稀疏张量中非零元素的数量。 - **is_scalar** - 是否为标量值标志。1 表示所有稀疏元素使用相同的值(`sparse_values[0]`),0 表示每个索引对应不同的值。 - **core_mask** - 核掩码(仅共享存储版本需要)。 输出: - **output** - 输出密集张量的数据数组。输出数组的大小由 `output_strides` 和最大索引值确定。未在 `indices_vec` 中指定的位置保持原值(调用前需要初始化)。 支持平台: ``FT78NE`` ``MT7004`` .. note:: - FT78NE 支持fp32, int8, int16, int32, fp64, cplx64, cplx128 - MT7004 支持fp16, fp32, int16, int32, cplx64 **共享存储版本:** .. c:function:: void i8_sparsetodense_s(int* indices_vec, int8_t* sparse_values, int8_t* output, int* output_strides, int sparse_length, int is_scalar, int core_mask) .. c:function:: void i16_sparsetodense_s(int* indices_vec, int16_t* sparse_values, int16_t* output, int* output_strides, int sparse_length, int is_scalar, int core_mask) .. c:function:: void i32_sparsetodense_s(int* indices_vec, int32_t* sparse_values, int32_t* output, int* output_strides, int sparse_length, int is_scalar, int core_mask) .. c:function:: void hp_sparsetodense_s(int* indices_vec, half* sparse_values, half* output, int* output_strides, int sparse_length, int is_scalar, int core_mask) .. c:function:: void fp_sparsetodense_s(int* indices_vec, float* sparse_values, float* output, int* output_strides, int sparse_length, int is_scalar, int core_mask) .. c:function:: void dp_sparsetodense_s(int* indices_vec, double* sparse_values, double* output, int* output_strides, int sparse_length, int is_scalar, int core_mask) .. c:function:: void c64_sparsetodense_s(int* indices_vec, float* sparse_values, float* output, int* output_strides, int sparse_length, int is_scalar, int core_mask) .. c:function:: void c128_sparsetodense_s(int* indices_vec, double* sparse_values, double* output, int* output_strides, int sparse_length, int is_scalar, int core_mask) **C调用示例(向量值模式):** .. code-block:: c :linenos: :emphasize-lines: 40-41 //FT78NE示例 #include #include int main(int argc, char* argv[]) { // 假设在DDR空间 // 输出密集张量形状 [2, 3, 4, 5] int output_shape[] = {2, 3, 4, 5}; // 计算步长:stride0 = 3*4*5 = 60, stride1 = 4*5 = 20, stride2 = 5, stride3 = 1 int output_strides[4]; output_strides[0] = 3 * 4 * 5; // 60 output_strides[1] = 4 * 5; // 20 output_strides[2] = 5; // 5 output_strides[3] = 1; // 第4维步长为1(未使用) // 稀疏元素:3个非零元素 int sparse_length = 3; // 索引:[[0,0,0,0], [0,1,2,3], [1,2,3,4]] int *indices_vec = (int *)0xA0000000; indices_vec[0] = 0; indices_vec[1] = 0; indices_vec[2] = 0; indices_vec[3] = 0; // 位置(0,0,0,0) indices_vec[4] = 0; indices_vec[5] = 1; indices_vec[6] = 2; indices_vec[7] = 3; // 位置(0,1,2,3) indices_vec[8] = 1; indices_vec[9] = 2; indices_vec[10] = 3; indices_vec[11] = 4; // 位置(1,2,3,4) // 稀疏值:每个索引对应不同的值 float *sparse_values = (float *)0xA1000000; sparse_values[0] = 1.0f; sparse_values[1] = 2.0f; sparse_values[2] = 3.0f; // 输出密集张量(需要预先初始化为0或默认值) float *output = (float *)0xB0000000; int output_size = 2 * 3 * 4 * 5; // 120 memset(output, 0, output_size * sizeof(float)); int is_scalar = 0; // 向量值模式 int core_mask = 0xff; fp_sparsetodense_s(indices_vec, sparse_values, output, output_strides, sparse_length, is_scalar, core_mask); return 0; } **C调用示例(标量值模式):** .. code-block:: c :linenos: :emphasize-lines: 32-33 //FT78NE示例 #include #include int main(int argc, char* argv[]) { // 假设在DDR空间 int output_strides[4]; output_strides[0] = 3 * 4 * 5; // 60 output_strides[1] = 4 * 5; // 20 output_strides[2] = 5; // 5 output_strides[3] = 1; int sparse_length = 3; // 索引:[[0,0,0,0], [0,1,2,3], [1,2,3,4]] int *indices_vec = (int *)0xA0000000; indices_vec[0] = 0; indices_vec[1] = 0; indices_vec[2] = 0; indices_vec[3] = 0; indices_vec[4] = 0; indices_vec[5] = 1; indices_vec[6] = 2; indices_vec[7] = 3; indices_vec[8] = 1; indices_vec[9] = 2; indices_vec[10] = 3; indices_vec[11] = 4; // 所有位置使用相同的值 float *sparse_values = (float *)0xA1000000; sparse_values[0] = 5.0f; // 只有这个值会被使用 float *output = (float *)0xB0000000; int output_size = 2 * 3 * 4 * 5; memset(output, 0, output_size * sizeof(float)); int is_scalar = 1; // 标量值模式 int core_mask = 0xff; fp_sparsetodense_s(indices_vec, sparse_values, output, output_strides, sparse_length, is_scalar, core_mask); return 0; } **私有存储版本:** .. c:function:: void i8_sparsetodense_p(int* indices_vec, int8_t* sparse_values, int8_t* output, int* output_strides, int sparse_length, int is_scalar) .. c:function:: void i16_sparsetodense_p(int* indices_vec, int16_t* sparse_values, int16_t* output, int* output_strides, int sparse_length, int is_scalar) .. c:function:: void i32_sparsetodense_p(int* indices_vec, int32_t* sparse_values, int32_t* output, int* output_strides, int sparse_length, int is_scalar) .. c:function:: void hp_sparsetodense_p(int* indices_vec, half* sparse_values, half* output, int* output_strides, int sparse_length, int is_scalar) .. c:function:: void fp_sparsetodense_p(int* indices_vec, float* sparse_values, float* output, int* output_strides, int sparse_length, int is_scalar) .. c:function:: void dp_sparsetodense_p(int* indices_vec, double* sparse_values, double* output, int* output_strides, int sparse_length, int is_scalar) .. c:function:: void c64_sparsetodense_p(int* indices_vec, float* sparse_values, float* output, int* output_strides, int sparse_length, int is_scalar) .. c:function:: void c128_sparsetodense_p(int* indices_vec, double* sparse_values, double* output, int* output_strides, int sparse_length, int is_scalar) **C调用示例(私有存储版本):** .. code-block:: c :linenos: :emphasize-lines: 31-32 //FT78NE示例 #include #include int main(int argc, char* argv[]) { // 假设在L2空间 int output_strides[4]; output_strides[0] = 3 * 4 * 5; // 60 output_strides[1] = 4 * 5; // 20 output_strides[2] = 5; // 5 output_strides[3] = 1; int sparse_length = 3; int *indices_vec = (int *)0x10000000; indices_vec[0] = 0; indices_vec[1] = 0; indices_vec[2] = 0; indices_vec[3] = 0; indices_vec[4] = 0; indices_vec[5] = 1; indices_vec[6] = 2; indices_vec[7] = 3; indices_vec[8] = 1; indices_vec[9] = 2; indices_vec[10] = 3; indices_vec[11] = 4; float *sparse_values = (float *)0x10001000; sparse_values[0] = 1.0f; sparse_values[1] = 2.0f; sparse_values[2] = 3.0f; float *output = (float *)0x10002000; int output_size = 2 * 3 * 4 * 5; memset(output, 0, output_size * sizeof(float)); int is_scalar = 0; fp_sparsetodense_p(indices_vec, sparse_values, output, output_strides, sparse_length, is_scalar); return 0; }